package com.sinodata.bsm.cicp.collector.common;

import java.io.BufferedReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.Collector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.CommandReader;
import com.sinodata.bsm.common.vo.ResPropertyValue;

/**
 * 
 * <p>
 * Description: unix进程采集程序 适用于 aix 、Solaris、linux、hp-unix
 * </p>
 *
 * @author liulibo
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-12-20 15:34:24      liulibo        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class ProcessCollector extends Collector {

    private static final Logger logger = Logger.getLogger(ProcessCollector.class);

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        String userName = this.getParamMap().get("Username");//用户名
        String procCmd = this.getParamMap().get("collectCmd");//采集命令
        String regexStr = this.getParamMap().get("Regex");//正则表达式
        String osName = this.getParamMap().get("SystemType");//系统类型
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();
        String[] propMetas = getPropMeta();
        String cmdStr = "UNIX95= ps";
        //判断命令行中是否包含用户名
        if (userName == null || userName.equals("") || userName.equals("-")) {
            cmdStr += " -e";
        } else {
            cmdStr += " -u " + userName;
        }
        if (osName.equalsIgnoreCase("aix") || osName.equalsIgnoreCase("linux") || osName.equalsIgnoreCase("hp")) {
            cmdStr += " -o 'pid,ppid,user,pcpu,vsz,flags,state,etime,time,args'|grep '";
        } else if (osName.equalsIgnoreCase("sun") || osName.equalsIgnoreCase("solaris")) {
            cmdStr += " -o 'pid,ppid,user,pcpu,vsz,f,s,etime,time,args'|grep '";
        }
        cmdStr += procCmd;
        cmdStr += "'|grep -v grep";
        //		String regexStr = "\\s*(\\d+)\\s+(\\d+)\\s+(\\S+)\\s+(\\d+\\.\\d+)\\s+(\\d+)\\s+(\\d+)\\s+([A-Z])\\s+(\\S+)\\s+(\\S+).*";
        BufferedReader reader = null;
        Pattern pattern = null;
        Matcher matcher = null;
        double cpuCost = 0.0; // 使用cpu占比
        long memCost = 0; // 使用内存大小
        char proState = ' '; // 进程状态
        long runTime = 0L; // 运行时长
        int proCount = 0; // 进程个数
        try {
            System.out.println(cmdStr);
            reader = CommandReader.getReader(ip, cmdStr, (int) this.interval, 0);
            pattern = Pattern.compile(regexStr);
            String line = null;
            char state = ' ';
            int s = 1;
            Long runtime = 0L;
            while ((line = reader.readLine()) != null) {
                matcher = pattern.matcher(line);
                if (matcher.find()) {
                    cpuCost = cpuCost + Double.parseDouble(matcher.group(4)); // 获取cpu占用值
                    memCost = memCost + Long.parseLong(matcher.group(5)); // 获取使用的内存
                    if (s == 1) {
                        state = matcher.group(7).charAt(0);//取得第一个进程的状态
                        runtime = getRunTime(matcher.group(8));//获得第一个进程的运行时长
                        s = 0;
                    }
                    if (matcher.group(2).equals("1")) { // 判断是否是主进程
                        proState = matcher.group(7).charAt(0); // 获取主进程的状态
                        runTime = getRunTime(matcher.group(8));//获得主进程的运行时长
                    }
                    proCount = proCount + 1;
                }
            }
            //如果没有找到ppid为1的父进程，则取第一个进程的状态
            if (proState == ' ') {
                proState = state;
            }
            //如果没有找到ppid为1的父进程，则取第一个进程的运行时长
            if (runTime == 0) {
                runTime = runtime;
            }
            if (proCount != 0) {
                cpuCost = cpuCost / proCount;
                memCost = memCost / proCount;
                runTime = runTime / proCount;
            } else {
                cpuCost = 0;
                memCost = 0;
                runTime = 0;
            }
            DecimalFormat numfor = (DecimalFormat) NumberFormat.getIntegerInstance();
            numfor.setParseIntegerOnly(true);
            numfor.applyPattern("0.00");
            ResPropertyValue propertyValueX = new ResPropertyValue();
            ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[propMetas.length];
            propValues[0] = ResPropertyValue.createPropValue(numfor.format(cpuCost), propMetas[0]);
            propValues[1] = ResPropertyValue.createPropValue(memCost + "", propMetas[1]);
            propValues[2] = ResPropertyValue.createPropValue(proState + "", propMetas[2]);
            propValues[3] = ResPropertyValue.createPropValue(runTime + "", propMetas[3]);
            propValues[4] = ResPropertyValue.createPropValue(proCount + "", propMetas[4]);
            propertyValueX.setValues(propValues);
            values.add(propertyValueX);
        } catch (IOException e) {
            logger.error("failed to collect by ProcessCollector", e);
            throw new CollectorException(e);
        }
        return values;
    }

    //获得进程的运行时长
    public Long getRunTime(String runtime) {
        Long runTime = 0L;
        String[] str = null;
        String[] str1 = null;
        // 对得到的运行时长的字符串的格式进行判断
        if (runtime.indexOf("-") != -1) {//判断是否有天数 天数-小时:分钟:秒
            str = runtime.split("-");
            str1 = str[1].split(":");
            runTime = Long.valueOf(str[0]) * 24 * 60 * 60 + Long.valueOf(str1[0]) * 60 * 60 + Long.valueOf(str1[1]) * 60 + Long.valueOf(str1[2]);
        } else {
            str1 = runtime.split(":");
            if (str1.length == 3) { //小时:分钟:秒
                runTime = Long.valueOf(str1[0]) * 60 * 60 + Long.valueOf(str1[1]) * 60 + Long.valueOf(str1[2]);
            } else {
                if (str1.length == 2) { //分钟:秒
                    runTime = Long.valueOf(str1[0]) * 60 + Long.valueOf(str1[1]);
                } else {
                    runTime = Long.valueOf(str1[2]);
                }
            }
        }
        return runTime;
    }

    @Override
    public String[] getParamMeta() {
        //        return new String[] { "用户名", "采集命令", "正则表达式", "指标个数", "系统类型" };
        return new String[] { "Username", "collectCmd", "Regex", "matchNum", "SystemType" };
    }

    @Override
    public String[] getPropMeta() {
        Pattern pattern = Pattern.compile(paramMap.get("Regex"));
        Matcher matcher = pattern.matcher("");
        //int count = Integer.parseInt(this.paramMap.get("matchNum"));//指标个数
        int count = matcher.groupCount();//指标个数
        String[] propMetas = new String[count];
        for (int i = 1; i <= propMetas.length; i++) {
            //            propMetas[i - 1] = "参数" + toChineseString(i);
            propMetas[i - 1] = "$" + i;
        }
        return propMetas;
    }

    /**
     * 最多只支持两位
     * 
     * @param number
     * @return
     */
    private static String toChineseString(int number) {
        if (number == 0) {
            return "零";
        }
        String chineseString = "";
        int n = number / 10;
        if (n > 0) {
            if (n > 1) {
                chineseString += toChineseNumber(n);
            }
            chineseString += "十";
        }
        n = number % 10;
        if (n > 0) {
            chineseString += toChineseNumber(n);
        }
        return chineseString;
    }

    private static String toChineseNumber(int number) {
        String[] chineseNumbers = new String[] { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
        return chineseNumbers[number];
    }

}
